<template>
	<div class="bg-white edu-common-param" style="padding: 10px 5px 0;">
		<el-button
			v-if="nullGroup"
			plain
			disabled
			type="info"
			class="disable-label"
		>{{$t('commonParam.message.nullGroup')+group}}</el-button>
		<div v-else>
			<div>
				<div class="float-left" style="margin-left: 10px;font-size: 20px">
					{{title?title:$t('commonParam.title')}} |
					<!-- 
            style="margin-left: 10px;color: #409EFF;"
            icon="el-icon-refresh"
					-->
					<el-button type="text" size="mini" @click="pageGroupParam">
						<span style="font-size: 12px">刷新</span>
					</el-button>
				</div>
				<div class="float-right">
					<el-button
						type="primary"
						size="mini"
						v-if="!simple"
						@click="startAddParam"
					>{{$t('commonParam.action.addParam')}}</el-button>&nbsp;
				</div>
			</div>
			<div v-if="groupParamsData && groupParamsData.length>0">
				<el-table
					:data="groupParamsData"
					@cell-mouse-enter="handlerHoverRow"
					@cell-mouse-leave="handlerOutRow"
					:max-height="tableMaxHeight"
				>
					<el-table-column type="expand" width="20">
						<template slot-scope="scope">
							<el-form label-position="left" class="param-table-expand">
								<el-form-item :label="$t('commonParam.param.remark')+': '">
									<span>{{scope.row.remark | remarkToName}}</span>
								</el-form-item>
								<el-form-item :label="$t('commonParam.param.detail')+': '">
									<span>{{ scope.row.remark| remarkToDetail }}</span>
								</el-form-item>
								<el-form-item :label="$t('commonParam.param.type')+': '">
									<span>{{ typesMap[scope.row.type] }}</span>
								</el-form-item>
								<el-form-item :label="$t('commonParam.param.value')+': '">
									<span>{{ scope.row.value }}</span>
								</el-form-item>
							</el-form>
						</template>
					</el-table-column>
					<el-table-column :label="$t('commonParam.param.remark')">
						<template slot-scope="scope">{{scope.row.remark | remarkToName}}</template>
					</el-table-column>
					<el-table-column prop="code" :label="$t('commonParam.param.code')"></el-table-column>
					<el-table-column prop="type" v-if="!simple" :label="$t('commonParam.param.type')"></el-table-column>
					<el-table-column prop="value" v-if="!simple" :label="$t('commonParam.param.value')"></el-table-column>
					<el-table-column :label="$t('commonParam.action.setting')" :width="simple?100:170">
						<template slot-scope="scope">
							<el-button
								v-if="!simple"
								type="text"
								@click="getValue(scope)"
								class="success"
							>{{$t('commonParam.action.testApi')}}</el-button>
							<template v-if="!(simple&&scope.row.type==='boolean')">
								<span v-if="simple&&hoverRowCode!==scope.row.code">{{scope.row.value}}</span>
								<el-button v-else type="text" @click="startEditParam(scope)">{{$t('message.edit')}}</el-button>
							</template>
							<el-switch
								v-else
								:active-value="'true'"
								:inactive-value="'false'"
								v-model="scope.row.value"
								@change="switchChange(scope)"
							></el-switch>
							<el-button
								v-if="!simple"
								type="text"
								class="danger"
								@click="deleteParam(scope)"
							>{{$t('message.delete')}}</el-button>
						</template>
					</el-table-column>
				</el-table>
				<div class="edu-pagination">
					<div class="float-right">
						<el-pagination
							small
							:current-page="page.num"
                            :page-sizes="[20, 50, 100, 500, 1000]"
							:page-size="page.size"
							:total="page.total"
							layout="total, sizes, prev, pager, next, jumper"
							style="float: right;margin:0;"
							@current-change="handleCurrentChange"
							@size-change="handleSizeChange"
						/>
					</div>
				</div>
			</div>
			<div
				v-if="groupParamsData && groupParamsData.length===0"
				class="disable-label"
				style="font-size:0"
			>
				<div v-if="simple" style="height:1px;"></div>
				<el-button v-else plain disabled type="info" class="disable-label">
					{{$t('commonParam.message.emptyGroup')}}
					<el-button
						v-if="groupDelete"
						type="danger"
						@click="deleteGroup"
					>{{$t('commonParam.action.deleteGroup')}}</el-button>
				</el-button>
			</div>
		</div>
		<el-dialog
			:title="editParam.isAdd?$t('commonParam.action.addParam'):$t('commonParam.action.editParam')"
			:visible.sync="dialogEditParam"
			width="350px"
			@close="cancelEditParam"
		>
			<el-form :model="editGroup">
				<el-form-item
					v-if="!simple"
					:label="$t('commonParam.param.remark')+':'"
					:label-width="'80px'"
					required
				>
					<el-input v-model.trim="editParam.remark" autocomplete="off"></el-input>
				</el-form-item>
				<el-form-item v-if="!simple" :label="$t('commonParam.param.detail')+':'" :label-width="'80px'">
					<el-input type="textarea" rows="1" v-model.trim="editParam.detail" autocomplete="off"></el-input>
				</el-form-item>
				<el-form-item
					v-if="!simple"
					:label="$t('commonParam.param.code')+':'"
					:label-width="'80px'"
					required
				>
					<el-input v-model.trim="editParam.code" autocomplete="off" @blur="checkParamCode($event)"></el-input>
				</el-form-item>
				<p v-if="editParam.codeCheck" class="edit-param-check">{{editParam.codeCheck}}</p>
				<el-form-item :label="$t('commonParam.param.type')+':'" :label-width="'80px'" required>
					<el-select
						v-if="editParam.isAdd"
						v-model="editParam.type"
						:placeholder="$t('commonParam.message.selectParamType')"
						value
						style="width:230px;"
					>
						<el-option v-for="(name,code) in typesMap" :key="code" :label="name" :value="code">
							<span style="float: left">{{ name }}</span>
							<span style="float: right; color: #8492a6; font-size: 13px">{{ code }}</span>
						</el-option>
					</el-select>
					<el-tag v-else>{{typesMap[editParam.type]}}</el-tag>
				</el-form-item>
				<el-form-item :label="$t('commonParam.param.value')+':'" :label-width="'80px'" required>
					<el-input
						v-if="editParam.type==='text'||editParam.type==='json'||editParam.type==='regexp'"
						type="textarea"
						rows="5"
						v-model.trim="editParam.value"
						autocomplete="off"
					></el-input>
					<el-input-number v-if="editParam.type==='number'" v-model.trim="editParam.value"></el-input-number>
					<template v-if="editParam.type==='boolean'">
						<el-radio v-model="editParam.value" label="true">true</el-radio>
						<el-radio v-model="editParam.value" label="false">false</el-radio>
					</template>
					<el-input
						v-if="!editParam.type"
						disabled
						:placeholder="$t('commonParam.message.selectParamType')"
					></el-input>
				</el-form-item>
				<p class="danger" v-if="editParam.check">{{editParam.check}}</p>
			</el-form>
			<div slot="footer" class="dialog-footer">
				<el-button @click="cancelEditParam">{{$t('message.cancel')}}</el-button>
				<el-button
					type="primary"
					:disabled="!editParamCheck"
					@click="saveEditParam"
				>{{$t('message.confirm')}}</el-button>
			</div>
		</el-dialog>
	</div>
</template>
<script>
import {
	getValue,
	getParam,
	addParam,
	updateParam,
	deleteParam,
	pageGroupParam,
	deleteGroup
} from "common/src/api/commonParam";

export default {
	name: "EduCommonParam",
	props: {
		title: {
			type: String
		},
		tableMaxHeight: {
			type: Number
		},
		group: {
			type: String,
			required: true
		},
		simple: Boolean,
		pageSize: {
			type: Number,
			default: 10
		},
		groupDelete: Boolean,
		hidden: {
			type: Boolean,
			default: false
		}
	},
	data() {
		return {
			nullGroup: false,
			hoverRowCode: null,
			typesMap: {
				boolean: "布尔值(boolean)",
				number: "数值(number)",
				json: "JSON",
				text: "普通文本(plain text)",
				regexp: "正则表达式(regular expression)"
			},
			groupParamsData: null,
			page: {
				size: this.pageSize,
				num: 1,
				total: 0
			},
			dialogEditParam: false,
			editParam: {
				oldCode: null,
				isAdd: false,
				groupCode: null,
				type: null,
				code: null,
				value: null,
				remark: null,
				detail: null,
				codeCheck: null,
				check: null
			}
		};
	},
	watch: {
		group(value) {
			this.page.num = 1;
			this.pageGroupParam();
		}
	},
	filters: {
		remarkToName(remark) {
			let match = remark.match(/^[^\n]+(?=\n)?/);
			return match ? match[0] : remark;
		},
		remarkToDetail(remark) {
			let split = remark.indexOf("\n");
			if (split >= 0) {
				return remark.substring(split + 1);
			} else {
				return null;
			}
		}
	},
	mounted() {
		this.pageGroupParam();
	},
	computed: {
		editParamCheck: function() {
			let param = this.editParam;

			return !(
				param.groupCode == null ||
				param.type == null ||
				param.remark == null ||
				param.remark === "" ||
				param.code == null ||
				param.value == null ||
				param.value === "" ||
				param.codeCheck != null
			);
		}
	},
	methods: {
		pageGroupParam: function() {
			pageGroupParam(this.group, this.page.num, this.page.size)
				.then(res => {
					if (res.list) {
						// console.log(res.list);
						if (this.hidden && res.list.length > 0) {
							this.groupParamsData = res.list.filter(
								param => param.hidden == 0
							);
						} else {
							this.groupParamsData = res.list;
						}

						this.page = {
							num: res.pageNum_,
							size: res.pageSize_,
							total: res.total_
						};
						this.nullGroup = false;
					} else {
						this.$message({
							type: "error",
							message: this.$t("commonParam.message.opsFail")
						});
						// this.nullGroup = true;
					}
				})
				.catch(() => {
					this.$message({
						type: "error",
						message: this.$t("commonParam.message.opsFail")
					});
					// this.nullGroup = true;
				});
		},
		handleCurrentChange: function(page) {
			this.$set(this.page, "num", page);
			this.pageGroupParam();
		},
		handleSizeChange(size) {
			this.$set(this.page, "size", size);
			this.pageGroupParam();
		},
		startAddParam: function() {
			this.editParam = {
				oldCode: null,
				isAdd: true,
				groupCode: this.group,
				type: null,
				code: null,
				value: null,
				codeCheck: null,
				remark: "",
				detail: "",
				check: null
			};
			this.dialogEditParam = true;
		},
		startEditParam: function(scope) {
			let value = scope.row.value;
			if (scope.row.type === "json") {
				value = eval(`JSON.stringify(${value},null,4)`);
			}
			let remark = scope.row.remark;
			let name, detail;
			if (remark) {
				let split = remark.indexOf("\n");

				if (split >= 0) {
					name = remark.substring(0, split);
					detail = remark.substring(split + 1);
				} else {
					name = remark;
					detail = "";
				}
			} else {
				name = "";
				detail = "";
			}

			this.editParam = {
				oldCode: scope.row.code,
				isAdd: false,
				groupCode: this.group,
				type: scope.row.type,
				value: value,
				code: scope.row.code,
				codeCheck: null,
				remark: name,
				detail,
				check: null
			};
			this.dialogEditParam = true;
		},
		cancelEditParam: function() {
			this.editParam = {
				oldCode: null,
				isAdd: false,
				groupCode: null,
				type: null,
				code: null,
				value: null,
				codeCheck: null,
				remark: null,
				check: null
			};
			this.dialogEditParam = false;
		},
		checkParamCode: function(e) {
			let code = e.target.value.trim();
			if (!/^[0-9a-zA-Z_]{1,40}$/.test(code)) {
				this.editParam.codeCheck = this.$t(
					"commonParam.message.codeIllegal"
				);
				return;
			}
			this.editParam.codeCheck = null;
			if (code !== this.editParam.oldCode)
				getParam(code).then(res => {
					if (res.data) {
						this.editParam.codeCheck = this.$t(
							"commonParam.message.codeDup"
						);
					} else {
						this.editParam.codeCheck = null;
					}
				});
		},
		saveEditParam: function() {
			if (this.editParam.type === "json") {
				// 如果是json 可能出现 key为数字的情况，这种情况下，后端可以解析（解析使用fastjson)，
				// 但是返回值时 jackson会报错，,我不知道怎么设置servicecomb使用fastjson,springboot常用设置默认json解析的方式测试不可用
				// 另外，JSON.parse也不支持 不带引号的key，因此在前端做特殊转换
				try {
					this.editParam.value = eval(
						`JSON.stringify(${this.editParam.value})`
					);
				} catch (e) {
					this.$message({
						type: "warning",
						message: this.$t("commonParam.message.jsonIllegal")
					});
					return;
				}
			}
			let callback = res => {
				if (res.code === 200) {
					this.$message({
						type: "success",
						message: this.editParam.isAdd
							? this.$t("message.addSuccess")
							: this.$t("message.editSuccess")
					});
					this.cancelEditParam();
					this.pageGroupParam();
				} else {
					this.$message({
						type: "warning",
						message: res.message
					});
					this.editParam.check = res.message;
				}
			};
			let catchCallback = err => {
				// console.log(JSON.stringify(err));
			};

			if (this.editParam.isAdd) {
				let vo = { ...this.editParam };
				if (vo.detail) vo.remark = vo.remark + "\n" + vo.detail;
				addParam(this.group, this.editParam)
					.then(callback)
					.catch(catchCallback);
			} else {
				let vo = {
					type: this.editParam.type,
					code: this.editParam.code,
					value: this.editParam.value
				};
				vo.remark = this.editParam.detail
					? this.editParam.remark + "\n" + this.editParam.detail
					: this.editParam.remark;
				updateParam(this.editParam.oldCode, vo)
					.then(callback)
					.catch(catchCallback);
			}
		},
		deleteParam: function(scope) {
			this.$confirm(
				this.$t("commonParam.message.confirmDeleteParam") +
					`：${scope.row.code}？`,
				{
					type: "warning"
				}
			)
				.then(() => {
					deleteParam(scope.row.code).then(res => {
						if (res.code === 200) {
							this.$message({
								type: "success",
								message: this.$t("message.deleteSuccess")
							});
							this.pageGroupParam();
						} else {
							this.$message({
								type: "warning",
								message: res.message
							});
						}
					});
				})
				.catch();
		},
		switchChange: function(scope) {
			this.editParam = {
				oldCode: scope.row.code,
				isAdd: false,
				groupCode: this.group,
				type: scope.row.type,
				value: scope.row.value,
				code: scope.row.code,
				codeCheck: null,
				remark: scope.row.remark,
				check: null
			};
			this.saveEditParam();
		},
		getValue: function(scope) {
			getValue(scope.row.code).then(res => {
				if (res.code === 200) {
					this.$message({
						type: "success",
						message: res.data
					});
					this.pageGroupParam();
				} else {
					this.$message({
						type: "warning",
						message: res.message
					});
				}
			});
		},
		deleteGroup: function() {
			let code = this.group;
			deleteGroup(code).then(res => {
				if (res.code === 200) {
					this.$message({
						type: "success",
						message: this.$t("message.deleteSuccess")
					});
					this.$emit("delete-group");
				}
			});
		},
		handlerHoverRow: function(row) {
			this.hoverRowCode = row.code;
		},
		handlerOutRow: function(row) {
			this.hoverRowCode = null;
		}
	}
};
</script>
<style>
.edu-common-param .el-table__row .cell {
	padding-left: 5px;
}
.edu-common-param .param-table-expand {
	font-size: 0;
}
.edu-common-param .param-table-expand label {
	width: 110px;
	color: #99a9bf;
}
.edu-common-param .el-table__expanded-cell {
	padding: 10px 50px;
}
.edu-common-param .param-table-expand .el-form-item {
	margin-right: 0;
	margin-bottom: 0;
}
.edu-common-param tr {
	height: 40px;
}
</style>
<style scoped>
.disable-label {
	height: 100%;
	width: 100%;
	font-size: x-large;
	color: #666;
	display: inline-block;
}
.danger {
	color: #f56c6c;
}
.success {
	color: #67c23a;
}
</style>
